package io.itit.ecp.admin.provide.handler;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
import io.itit.ecp.admin.common.constants.EcpAdminConstants;
import io.itit.ecp.admin.common.enums.IDataRangeEnums.RangeLevel;
import io.itit.ecp.admin.provide.helper.DataRangeHelper;
import io.itit.ecp.admin.provide.properties.DataRangeConfigProperties;
import io.itit.grass.common.exception.GrassAuthException;
import io.itit.grass.web.wall.helper.UserHelper;
import io.itit.grass.web.wall.utils.ShiroUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.schema.Table;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 自定义数据范围
 *
 * @Author Roy
 * @Date 2024-01-09 16:52
 */
@Slf4j
@Data
public class DataRangeHandler implements MultiDataPermissionHandler {

    protected final DataRangeConfigProperties properties;

    @Override
    public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
        /**
         * 以下四种情况直接放行
         * 1、如果数据范围权限未开启
         * 2、服务器启动时数据范围辅助对象未初始化
         * 3、如果未配置数据权限表 或者 非指定的数据权限表就直接放行
         * 4、当前线程设置了放行策略
         * 5、超级管理员用户或者超级管理员角色直接放行
         */
        if (!properties.getEnable() || Objects.isNull(DataRangeHelper.i())) {
            return null;
        }

        // 表名
        String tableName = table.getName();

        // 需要做数据权限控制的表集合
        Map<String, List<String>> tableMap = properties.getTableMap();

        // 如果未配置数据权限表 或者 非指定的数据权限表就直接放行
        if (tableMap == null || !tableMap.containsKey(tableName)) {
            return null;
        }

        // 如果当前线程设置了放行策略直接放行
        if (DataRangeHelper.i().has()) {
            return null;
        }

        // 当前登录用户
        String userId = ShiroUtils.getUserId();

        // 超级管理员用户或者超级管理员角色直接放行
        if (UserHelper.i().isAdmin(userId)) {
            return null;
        }

        // 数据权限范围级别
        String dataRangeLevel = DataRangeHelper.i().getDataRangeLevel(userId);
        // 如果为空就重新初始化一下
        dataRangeLevel = StringUtils.isEmpty(dataRangeLevel) ? DataRangeHelper.i().initDataRange(userId) : dataRangeLevel;
        if (EcpAdminConstants.NO.equals(dataRangeLevel)) {
            if (StringUtils.isEmpty(userId)) {
                return null;
            }
            throw new GrassAuthException("无数据访问权限！");
        }

        // 所有权限 >> 直接放行
        if (RangeLevel.rangeLevelAll.rangeLevel.equals(dataRangeLevel)) {
            return null;
        }

        return DataRangeHelper.i().dataRangeLevelHelper(dataRangeLevel).getSqlSegment(table, where, mappedStatementId, tableMap);
    }

}
